#include "serial.h"

// 波特率映射表
typedef struct
{
    int baud_rate;
    speed_t speed;
} BaudRateMap;

static const BaudRateMap baud_rate_map[] =
{
    {50, B50},
    {75, B75},
    {110, B110},
    {134, B134},
    {150, B150},
    {200, B200},
    {300, B300},
    {600, B600},
    {1200, B1200},
    {1800, B1800},
    {2400, B2400},
    {4800, B4800},
    {9600, B9600},
    {19200, B19200},
    {38400, B38400},
    {57600, B57600},
    {115200, B115200},
    {230400, B230400},
    {460800, B460800},
    {500000, B500000},
    {576000, B576000},
    {921600, B921600},
    {1000000, B1000000},
    {1152000, B1152000},
    {1500000, B1500000},
    {2000000, B2000000},
    {2500000, B2500000},
    {3000000, B3000000},
    {3500000, B3500000},
    {4000000, B4000000},
    {0, B0}  // 结束标记
};

int open_serial_port(const char *device)
{
    int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0)
    {
        perror("open serial");
        return -1;
    }

    // 恢复阻塞模式
    if (fcntl(fd, F_SETFL, 0) < 0)
    {
        perror("fcntl");
        close(fd);
        return -1;
    }

    return fd;
}

int configure_serial_port(int fd, int baud_rate, int data_bits,
                          int stop_bits, char parity, bool flow_control)
{
    struct termios tty;
    memset(&tty, 0, sizeof(tty));

    if (tcgetattr(fd, &tty))
    {
        perror("tcgetattr");
        return -1;
    }

    // 查找匹配的波特率
    speed_t speed = B9600;  // 默认值
    for (const BaudRateMap *map = baud_rate_map; map->baud_rate != 0; map++)
    {
        if (map->baud_rate == baud_rate)
        {
            speed = map->speed;
            break;
        }
    }

    // 设置波特率
    cfsetispeed(&tty, speed);
    cfsetospeed(&tty, speed);

    // 设置数据位
    tty.c_cflag &= ~CSIZE;
    switch (data_bits)
    {
        case 5: tty.c_cflag |= CS5; break;
        case 6: tty.c_cflag |= CS6; break;
        case 7: tty.c_cflag |= CS7; break;
        case 8: tty.c_cflag |= CS8; break;
        default: tty.c_cflag |= CS8;  // 默认8位
    }

    // 设置停止位
    if (stop_bits == 2)
    {
        tty.c_cflag |= CSTOPB;
    }
    else
    {
        tty.c_cflag &= ~CSTOPB;  // 默认1位停止位
    }

    // 设置校验位
    switch (parity)
    {
        case 1:  // 奇校验
            tty.c_cflag |= PARENB;
            tty.c_cflag |= PARODD;
            break;
        case 2:  // 偶校验
            tty.c_cflag |= PARENB;
            tty.c_cflag &= ~PARODD;
            break;
        case 0:  // 无校验
        default:
            tty.c_cflag &= ~PARENB;
            break;
    }

    // 流控设置
    if (flow_control)
    {
        tty.c_cflag |= CRTSCTS;
    }
    else
    {
        tty.c_cflag &= ~CRTSCTS;
    }

    // 其他设置
    tty.c_cflag |= (CLOCAL | CREAD);  // 忽略调制解调器控制线，启用接收器
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  // 非规范模式
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);  // 关闭软件流控
    tty.c_iflag &= ~ICRNL;  // 禁止将输入的CR转换为NL
    tty.c_oflag &= ~OPOST;  // 原始输出

    // 超时和最小读取字符数
    tty.c_cc[VMIN] = 0;
    tty.c_cc[VTIME] = 0;

    // 应用设置
    if (tcsetattr(fd, TCSANOW, &tty))
    {
        perror("tcsetattr");
        return -1;
    }

    // 清空缓冲区
    tcflush(fd, TCIOFLUSH);

    return 0;
}

void close_serial_port(int fd)
{
    close(fd);
}